/* Copyright (c) 2004-2024 Peigen.info. All rights reserved. */

package info.peigen.hotpot.business.customer.core.domain.action;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import info.peigen.hotpot.business.account.core.domain.account.action.AccountConvertor;
import info.peigen.hotpot.business.customer.core.domain.*;
import info.peigen.hotpot.business.customer.core.domain.auth.CustomerAuthentication;
import info.peigen.hotpot.business.customer.core.domain.auth.CustomerAuthenticationBase;
import info.peigen.hotpot.business.customer.core.domain.auth.CustomerAuthenticationIdentity;
import info.peigen.hotpot.business.customer.core.domain.auth.CustomerAuthenticationLog;
import info.peigen.hotpot.business.customer.core.domain.operator.CustomerOperator;
import info.peigen.hotpot.business.customer.core.domain.operator.CustomerOperatorActive;
import info.peigen.hotpot.business.customer.core.domain.operator.CustomerOperatorBase;
import info.peigen.hotpot.business.customer.core.domain.partner.action.PartnerConverter;
import info.peigen.hotpot.business.customer.core.domain.weixin.miniapp.WxMiniappUser;
import info.peigen.hotpot.business.customer.core.repository.entity.*;
import info.peigen.hotpot.business.customer.facade.info.*;
import info.peigen.hotpot.business.customer.facade.info.weixin.miniapp.CustomerWxMiniappUserInfo;
import info.peigen.hotpot.business.customer.facade.order.log.CustomerLogOrder;
import info.peigen.hotpot.common.core.domain.Identity;
import info.peigen.hotpot.common.core.domain.Image;
import info.peigen.hotpot.common.core.result.ResultCode;
import info.peigen.hotpot.common.service.base.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <b>(CustomerConverter)</b>
 *
 * @author Peigen
 * @version 1.0.0
 * @since 2021/8/5
 */
@Slf4j
public class CustomerConverter {
    public static WxMiniappUser convert(CustomerWxMiniappUserInfo userInfo) {
        return BeanUtil.copyProperties(userInfo, WxMiniappUser.class);
    }

    public static CustomerPageInfo convert(CustomerEntity entity) {
        return BeanUtil.copyProperties(entity, CustomerPageInfo.class);
    }

    public static Customer simpleWechatConvert(CustomerEntity entity, CustomerTechEntity techEntity) {
        return Customer.builder()
                .customerId(entity.getCustomerId())
                .customerBase(CustomerBase.builder()
                        .mobile(entity.getMobile())
                        .qq(entity.getQq())
                        .email(entity.getEmail())
                        .address(entity.getAddress())
                        .nickname(entity.getNickname())
                        .wechat(entity.getWechat())
                        .avatar(JSON.parseObject(entity.getAvatar(), Image.class))
                        .build())
                .customerTech(BeanUtil.copyProperties(techEntity, CustomerTech.class))
                .build();
    }

    public static CustomerInfo convertInfo(CustomerEntity entity) {
        return BeanUtil.copyProperties(entity, CustomerInfo.class);
    }

    public static CustomerManageInfo convertManageInfo(CustomerEntity entity) {
        CustomerManageInfo customerManageInfo = BeanUtil.copyProperties(entity, CustomerManageInfo.class, "avatar");
        if (ObjectUtil.isNotNull(entity) && ObjectUtil.isNotNull(entity.getAvatar())) {
            customerManageInfo.setAvatar(JSON.parseObject(entity.getAvatar(), Image.class));
        }
        return customerManageInfo;
    }

    public static CustomerEntity convertCustomer(Customer customer) {
        CustomerEntity entity = new CustomerEntity();
        // entity.setOpenid(customer.getCustomerTech().getWxMiniappUser().getOpenid());
        BeanUtil.copyProperties(customer, entity, "customerPermission", "avatar");
        entity.setPermission(JSON.toJSONString(customer.getPermission()));
        BeanUtil.copyProperties(customer.getLevel(), entity, CopyOptions.create().setIgnoreNullValue(true));
        BeanUtil.copyProperties(customer.getCustomerBase(), entity, CopyOptions.create().setIgnoreNullValue(true).setIgnoreProperties("avatar"));
        entity.setAvatar(JSON.toJSONString(customer.getCustomerBase().getAvatar()));
        BeanUtil.copyProperties(customer.getCustomerMarketing(), entity, CopyOptions.create().setIgnoreNullValue(true));

        return entity;
    }

    public static Customer convertCustomer(CustomerEntity customerEntity, List<CustomerOperatorEntity> customerOperatorEntities,
                                           CustomerAuthenticationEntity customerAuthenticationEntity,
                                           CustomerAuthenticationBaseEntity customerAuthenticationBaseEntity,
                                           List<CustomerAuthenticationIdentityEntity> customerAuthenticationIdentityEntities,
                                           List<CustomerAuthenticationLogEntity> customerAuthenticationLogEntities,
                                           CustomerTechEntity customerTechEntity, PartnerEntity partnerEntity) {
        List<CustomerOperator> customerOperators = convertCustomerOperatorEntities(customerOperatorEntities);
        CustomerAuthentication customerAuthentication = convertCustomerAuthenticationEntity(customerAuthenticationEntity, customerAuthenticationBaseEntity,
                customerAuthenticationIdentityEntities, customerAuthenticationLogEntities);
        Customer     customer     = new Customer();
        CustomerBase customerBase = new CustomerBase();
        BeanUtil.copyProperties(customerEntity, customer, "permission");
        customer.setLevel(BeanUtil.copyProperties(customerEntity, CustomerLevel.class));
        BeanUtil.copyProperties(customerEntity, customerBase, "avatar");
        customerBase.setAvatar(JSON.parseObject(customerEntity.getAvatar(), Image.class));
        customerBase.setAddress(customerEntity.getAddress());
        customerBase.setNickname(customerEntity.getNickname());
        customer.setOperators(customerOperators);
        customer.setMasterOperator(CustomerOperator.findMasterOperator(customerOperators));
        customer.setAuthentication(customerAuthentication);
        customer.setCustomerBase(customerBase);
        customer.setPermission(JSON.parseObject(customerEntity.getPermission(), CustomerPermission.class));
        customer.setCustomerTech(BeanUtil.copyProperties(customerTechEntity, CustomerTech.class));

        CustomerMarketing customerMarketing = new CustomerMarketing();
        BeanUtil.copyProperties(customerEntity, customerMarketing);
        customer.setCustomerMarketing(customerMarketing);
        customer.getCustomerTech().setPartner(PartnerConverter.convert(partnerEntity));
        return customer;
    }

    public static CustomerOperatorEntity convertCustomerOperator(CustomerOperator customerOperator) {
        CustomerOperatorEntity entity = new CustomerOperatorEntity();
        BeanUtil.copyProperties(customerOperator, entity);
        BeanUtil.copyProperties(customerOperator.getBaseInfo(), entity);
        BeanUtil.copyProperties(customerOperator.getActiveInfo(), entity);
        return entity;
    }

    public static List<CustomerOperatorEntity> convertCustomerOperatorEntities(Customer customer) {
        return customer.getOperators().stream().map(operator -> {
            CustomerOperatorEntity entity = convertCustomerOperator(operator);
            entity.setCustomerId(customer.getCustomerId());
            return entity;
        }).collect(Collectors.toList());
    }

    public static CustomerOperator convertCustomerOperator(CustomerOperatorEntity customerOperatorEntity) {
        CustomerOperator       customerOperator       = new CustomerOperator();
        CustomerOperatorBase   customerOperatorBase   = new CustomerOperatorBase();
        CustomerOperatorActive customerOperatorActive = new CustomerOperatorActive();
        BeanUtil.copyProperties(customerOperatorEntity, customerOperator);
        BeanUtil.copyProperties(customerOperatorEntity, customerOperatorBase);
        BeanUtil.copyProperties(customerOperatorEntity, customerOperatorActive);
        customerOperator.setBaseInfo(customerOperatorBase);
        customerOperator.setActiveInfo(customerOperatorActive);
        return customerOperator;
    }

    private static List<CustomerOperator> convertCustomerOperatorEntities(List<CustomerOperatorEntity> customerOperatorEntities) {
        return customerOperatorEntities.stream().map(operator -> {
            CustomerOperator       customerOperator       = new CustomerOperator();
            CustomerOperatorBase   customerOperatorBase   = new CustomerOperatorBase();
            CustomerOperatorActive customerOperatorActive = new CustomerOperatorActive();
            BeanUtil.copyProperties(operator, customerOperator);
            BeanUtil.copyProperties(operator, customerOperatorBase);
            BeanUtil.copyProperties(operator, customerOperatorActive);
            customerOperator.setBaseInfo(customerOperatorBase);
            customerOperator.setActiveInfo(customerOperatorActive);
            return customerOperator;
        }).collect(Collectors.toList());
    }

    public static CustomerAuthenticationEntity convertCustomerAuthenticationEntity(Customer customer) {
        if (ObjectUtil.isNull(customer.getAuthentication())) {
            return null;
        }
        CustomerAuthenticationEntity entity = BeanUtil.copyProperties(customer.getAuthentication(), CustomerAuthenticationEntity.class);
        entity.setCustomerId(customer.getCustomerId());
        return entity;
    }

    public static CustomerAuthenticationBaseEntity convertCustomerAuthenticationBaseEntity(Customer customer) {
        if (ObjectUtil.isNull(customer.getAuthentication()) || ObjectUtil.isNull(customer.getAuthentication().getCustomerAuthenticationBase())) {
            return null;
        }
        CustomerAuthenticationBaseEntity entity = BeanUtil.copyProperties(customer.getAuthentication().getCustomerAuthenticationBase(), CustomerAuthenticationBaseEntity.class);
        entity.setCustomerId(customer.getCustomerId());
        return entity;
    }

    public static List<CustomerAuthenticationIdentityEntity> convertAuthenticatorIdentityEntities(Customer customer) {
        if (ObjectUtil.isNull(customer.getAuthentication()) || ObjectUtil.isNull(customer.getAuthentication().getIdentities())) {
            return null;
        }
        return JSON.parseArray(JSON.toJSONString(customer.getAuthentication().getIdentities()), CustomerAuthenticationIdentityEntity.class);
    }

    public static List<CustomerAuthenticationLogEntity> convertAuthenticationLogEntities(Customer customer) {
        List<CustomerAuthenticationLogEntity> customerAuthenticationLogEntities = new ArrayList<>();
        if (!CollUtil.isEmpty(customer.getAuthentication().getLogs())) {
            customerAuthenticationLogEntities = JSON.parseArray(JSON.toJSONString(customer.getAuthentication().getLogs()), CustomerAuthenticationLogEntity.class);
        }
        return customerAuthenticationLogEntities;
    }

    public static CustomerLogEntity convertCustomerLog(CustomerLogOrder order) {
        return BeanUtil.copyProperties(order, CustomerLogEntity.class);
    }

    public static List<CustomerLog> convertCustomerLogList(List<CustomerLogEntity> customerUpdateLogEntities) {
        return customerUpdateLogEntities.stream().map(log -> {
            CustomerLog customerLog = new CustomerLog();
            BeanUtil.copyProperties(log, customerLog);
            return customerLog;
        }).collect(Collectors.toList());
    }

    private static CustomerAuthentication convertCustomerAuthenticationEntity(CustomerAuthenticationEntity customerAuthenticationEntity, CustomerAuthenticationBaseEntity customerAuthenticationBaseEntity, List<CustomerAuthenticationIdentityEntity> customerAuthenticationIdentityEntities, List<CustomerAuthenticationLogEntity> customerAuthenticationLogEntities) {
        CustomerAuthentication     customerAuthentication     = new CustomerAuthentication();
        CustomerAuthenticationBase customerAuthenticationBase = new CustomerAuthenticationBase();
        Identity                   legalRepresentative        = new Identity();
        BeanUtil.copyProperties(customerAuthenticationEntity, customerAuthentication);
        BeanUtil.copyProperties(customerAuthenticationBaseEntity, customerAuthenticationBase);
        BeanUtil.copyProperties(customerAuthenticationBaseEntity, legalRepresentative, "address");

        customerAuthenticationBase.setLegalRepresentative(legalRepresentative);
        customerAuthentication.setCustomerAuthenticationBase(customerAuthenticationBase);
        customerAuthentication.setIdentities(JSON.parseArray(JSON.toJSONString(customerAuthenticationIdentityEntities), CustomerAuthenticationIdentity.class));
        customerAuthentication.setLogs(JSON.parseArray(JSON.toJSONString(customerAuthenticationLogEntities), CustomerAuthenticationLog.class));
        return customerAuthentication;
    }

    public static CustomerInfo convertCustomerInfo(Customer customer) {
        CustomerInfo customerInfo = new CustomerInfo();
        customerInfo.setAuthenticatorInfo(convertCustomerAuthenticationInfo(customer.getAuthentication()));
        BeanUtil.copyProperties(customer, customerInfo, "customerPermission");
        customerInfo.setPermission(JSON.toJSONString(customer.getPermission()));
        customerInfo.setLevel(BeanUtil.copyProperties(customer.getLevel(), CustomerLevelInfo.class));
        customerInfo.setBaseInfo(BeanUtil.copyProperties(customer.getCustomerBase(), CustomerBaseInfo.class));
        customerInfo.setMasterOperatorInfo(BeanUtil.copyProperties(customer.getMasterOperator(), CustomerOperatorInfo.class));
        customerInfo.setOperatorInfos(convertCustomerOperatorInfos(customer.getOperators()));
        customerInfo.setHasPayPassword(StrUtil.isNotEmpty(customer.getMasterOperator().getPayPassword()));
        customerInfo.setMarketingInfo(BeanUtil.copyProperties(customer.getCustomerMarketing(), CustomerMarketingInfo.class));
        customerInfo.setAccounts(Collections.singletonList(AccountConvertor.convertAccountInfo(customer.getAccount())));
        if (customer.getCustomerFeeRule() != null) {
            customerInfo.setCustomerFeeRuleInfo(BeanUtil.copyProperties(customer.getCustomerFeeRule(), CustomerFeeRuleInfo.class));
        }
        customerInfo.setCustomerTechBaseInfo(
                CustomerTechBaseInfo.builder()
                        .partnerId(customer.getCustomerTech().getPartnerId())
                        .partnerPublicKeyStr(customer.getCustomerTech().getPartner().getTech().getPartnerPublicKeyStr())
                        .partnerAbbreviation(customer.getCustomerTech().getPartner().getAbbreviation())
                        .userInfo(BeanUtil.copyProperties(customer.getCustomerTech().getWxMiniappUser(), CustomerWxMiniappUserInfo.class))
                        .build());
        return customerInfo;
    }

    public static CustomerOperatorInfo convertCustomerOperatorInfo(CustomerOperator customerOperator) {
        Assert.notNull(customerOperator, () -> new BusinessException(ResultCode.FAILURE, "CustomerOperator不得为空!"));
        return BeanUtil.copyProperties(customerOperator, CustomerOperatorInfo.class);
    }

    public static List<CustomerOperatorInfo> convertCustomerOperatorInfos(List<CustomerOperator> customerOperators) {
        Assert.notNull(customerOperators, () -> new BusinessException(ResultCode.FAILURE, "CustomerOperators不得为空!"));
        return customerOperators.stream().map(operator -> convertCustomerOperatorInfo(operator)).collect(Collectors.toList());
    }

    public static CustomerOperatorActiveInfo convertCustomerOperatorActiveInfo(CustomerOperatorActive active) {
        Assert.notNull(active);
        Assert.notNull(active, () -> new BusinessException(ResultCode.FAILURE, "CustomerOperatorActive不得为空!"));
        return BeanUtil.copyProperties(active, CustomerOperatorActiveInfo.class);
    }

    public static CustomerOperatorBaseInfo convertCustomerOperatorBaseInfo(CustomerOperatorBase base) {
        Assert.notNull(base, () -> new BusinessException(ResultCode.FAILURE, "CustomerOperatorBase不得为空!"));
        return BeanUtil.copyProperties(base, CustomerOperatorBaseInfo.class);
    }

    public static CustomerAuthenticationInfo convertCustomerAuthenticationInfo(CustomerAuthentication customerAuthentication) {
        if (ObjectUtil.isNull(customerAuthentication)) {
            return null;
        }
        CustomerAuthenticationInfo customerAuthenticationInfo = new CustomerAuthenticationInfo();
        BeanUtil.copyProperties(customerAuthentication, customerAuthenticationInfo);

        // 基础信息
        if (ObjectUtil.isNotNull(customerAuthentication.getCustomerAuthenticationBase())) {
            CustomerAuthenticationBaseInfo customerAuthenticationBaseInfo = new CustomerAuthenticationBaseInfo();
            BeanUtil.copyProperties(customerAuthentication.getCustomerAuthenticationBase(), customerAuthenticationBaseInfo);
            customerAuthenticationInfo.setCustomerAuthenticationBaseInfo(customerAuthenticationBaseInfo);
        }

        // 身份信息
        List<CustomerAuthenticationIdentity> identities = customerAuthentication.getIdentities();
        if (!CollUtil.isEmpty(identities)) {
            customerAuthenticationInfo.setCustomerAuthenticationIdentityInfos(JSON.parseArray(JSON.toJSONString(identities), CustomerAuthenticationIdentityInfo.class));
        }

        // 日志信息
        List<CustomerAuthenticationLog> logs = customerAuthentication.getLogs();
        if (!CollUtil.isEmpty(logs)) {
            customerAuthenticationInfo.setCustomerAuthenticationLogInfos(JSON.parseArray(JSON.toJSONString(logs), CustomerAuthenticationLogInfo.class));
        }

        return customerAuthenticationInfo;
    }

    public static CustomerTechEntity convertCustomerTech(Customer customer) {
        Assert.notNull(customer, () -> new BusinessException(ResultCode.FAILURE, "Customer不得为空!"));
        Assert.notNull(customer.getCustomerTech(), () -> new BusinessException(ResultCode.FAILURE, "CustomerTech不得为空!"));
        CustomerTechEntity customerTechEntity = BeanUtil.copyProperties(customer.getCustomerTech(), CustomerTechEntity.class)
                .setCustomerId(customer.getCustomerId());
        customerTechEntity.setPartnerId(customer.getCustomerTech().getPartner().getPartnerId());
        return customerTechEntity;
    }

}